home *** CD-ROM | disk | FTP | other *** search
- /*
- * draw.c
- *
- * This file is part of the basis of the Forms Library
- *
- * It contains lowlevel routines to draw boxes, text, etc. These routines
- * are used by the object drawing routines for objects.
- *
- * Written by Mark Overmars
- *
- * Version 2.2 a
- * Date: Jun 21, 1993
- */
-
- #include <malloc.h>
- #include <stdio.h>
- #include "gl/gl.h"
- #include "gl/device.h"
- #include "fmclient.h"
- #include <string.h>
- #include "forms.h"
-
- /*********
- Mouse stuff.
- *********/
-
- void fl_get_mouse(float *xx,float *yy)
- /* returns the position of the mouse in world coordinates*/
- {
- long x,y;
- getorigin(&x,&y);
- *xx = (float) (getvaluator(MOUSEX)-x);
- *yy = (float) (getvaluator(MOUSEY)-y);
- }
-
- /*********
- Clipping.
- *********/
-
- void fl_set_clipping(float x,float y,float w,float h)
- /* Sets the clipping region */
- {
- Screencoord sl,sr,sb,st;
- sl = (short) (x);
- sr = (short) (sl + w - 1.0);
- sb = (short) (y);
- st = (short) (sb + h - 1.0);
- scrmask(sl,sr,sb,st);
- }
-
- void fl_unset_clipping()
- /* Resets the clipping region */
- {
- Screencoord sl,sr,sb,st;
- getviewport(&sl,&sr,&sb,&st);
- scrmask(sl,sr,sb,st);
- }
-
- /*********
- Font related stuff
- *********/
-
- typedef struct {
- int defined; /* Whether the font is defined */
- char name[64]; /* Name of the font */
- int fnumb; /* Number of sizes in use */
- float size[32]; /* different sizes in use */
- fmfonthandle fhandle[32]; /* handles for different sizes */
- } FL_FONT;
-
- static FL_FONT fl_font[FL_MAXFONT]; /* The fonts used */
-
- static fmfonthandle use_font(int numb, float size)
- /* Returns the handle to font numb in the required size. */
- {
- int i;
- /* Error checking */
- if (numb < 0 || numb >= FL_MAXFONT)
- {
- fl_error("use_font","Trying to use non-existing font");
- return use_font(0,FL_NORMAL_FONT);
- }
- if (!fl_font[numb].defined)
- {
- fl_error("use_font","Trying to use undefined font");
- return use_font(0,FL_NORMAL_FONT);
- }
- /* Create basic font if required */
- if (fl_font[numb].fnumb == 0)
- {
- fl_font[numb].fhandle[0] = fmfindfont(fl_font[numb].name);
- /* Check whether existing */
- if (fl_font[numb].fhandle[0] == NULL)
- fl_font[numb].fhandle[0] = fmfindfont(fl_font[0].name);
- fl_font[numb].fnumb = 1;
- }
- /* Search for the required size. */
- for (i=1; i<fl_font[numb].fnumb; i++)
- if (size == fl_font[numb].size[i])
- return fl_font[numb].fhandle[i];
- /* If not available, create it */
- if (fl_font[numb].fnumb == 32)
- {
- fmfreefont(fl_font[numb].fhandle[31]);
- fl_font[numb].fnumb--;
- }
- fl_font[numb].size[fl_font[numb].fnumb] = size;
- fl_font[numb].fhandle[fl_font[numb].fnumb] =
- fmscalefont(fl_font[numb].fhandle[0],size);
- fl_font[numb].fnumb++;
- return fl_font[numb].fhandle[fl_font[numb].fnumb-1];
- }
-
- void fl_set_font_name(int numb, char name[])
- /* Sets the name of a particular font number. */
- {
- int i;
- if (numb < 0 || numb >= FL_MAXFONT)
- {
- fl_error("fl_set_font_name","Setting name of non-existing font number.");
- return;
- }
- if (fl_font[numb].defined)
- for (i=0; i < fl_font[numb].fnumb; i++)
- fmfreefont(fl_font[numb].fhandle[i]);
- fl_font[numb].defined = TRUE;
- strcpy(fl_font[numb].name,name);
- fl_font[numb].fnumb = 0;
- }
-
- void fl_set_font(char normalname[], char boldname[],
- char italicname[], char fixedname[])
- /* Old style setting routine. WILL BE REMOVED IN THE FUTURE. */
- {
- fl_set_font_name(0,normalname);
- fl_set_font_name(1,boldname);
- fl_set_font_name(2,italicname);
- fl_set_font_name(3,fixedname);
- }
-
- void fl_init_fonts()
- /* Initializes the fonts being used to the defaults */
- {
- int i;
- for (i=0; i<FL_MAXFONT;i++) fl_font[i].defined = FALSE;
- fminit();
- fl_set_font_name(0,FL_FONT_NAME_0);
- fl_set_font_name(1,FL_FONT_NAME_1);
- fl_set_font_name(2,FL_FONT_NAME_2);
- fl_set_font_name(3,FL_FONT_NAME_3);
- fl_set_font_name(4,FL_FONT_NAME_4);
- fl_set_font_name(5,FL_FONT_NAME_5);
- fl_set_font_name(6,FL_FONT_NAME_6);
- fl_set_font_name(7,FL_FONT_NAME_7);
- fl_set_font_name(8,FL_FONT_NAME_8);
- fl_set_font_name(9,FL_FONT_NAME_9);
- fl_set_font_name(10,FL_FONT_NAME_10);
- fl_set_font_name(11,FL_FONT_NAME_11);
- fl_set_font_name(12,FL_FONT_NAME_12);
- fl_set_font_name(13,FL_FONT_NAME_13);
- fl_set_font_name(14,FL_FONT_NAME_14);
- fl_set_font_name(15,FL_FONT_NAME_15);
- }
-
- float fl_get_char_height(float size, int style)
- /* returns the height of the current font in size points */
- {
- fmfontinfo info;
- fmfonthandle fnt = use_font(style,size);
- if (fnt == NULL) return 0.0;
- fmgetfontinfo(fnt,&info);
- return (float) info.height;
- }
-
- float fl_get_string_width(float size, int style, char str[])
- /* returns the width of the given string */
- {
- fmfontinfo info;
- fmfonthandle fnt = use_font(style,size);
- if (fnt == NULL) return 0.0;
- fmgetfontinfo(fnt,&info);
- return (float) fmgetstrwidth(fnt,str);
- }
-
- float fl_get_char_width(float size, int style, char ch)
- /* returns the width of the given character */
- {
- char str[2];
- str[0] = ch; str[1] = '\0';
- return fl_get_string_width(size,style,str);
- }
-
- /*********
- Color Stuff.
- *********/
-
- static short fl_red[4096], fl_green[4096], fl_blue[4096];
-
- void fl_init_colormap()
- {
- long cmwin;
- int i;
- /* Read colormap colors into internal table */
- fl_save_user_window();
- noport();
- cmwin = winopen("CM");
- for (i=0; i<4096; i++)
- {fl_red[i] = 0; fl_green[i] = 0; fl_blue[i] = 0; }
- for (i=0; i<256; i++)
- getmcolor(i,&fl_red[i],&fl_green[i],&fl_blue[i]);
- winclose(cmwin);
- fl_restore_user_window();
- /* Correct colors for small number of bitplanes */
- if (getgdesc(GD_BITS_NORM_DBL_RED) <= 4)
- for (i=0; i<256; i++)
- {
- fl_red[i] = 8 * (fl_red[i] / 8);
- fl_green[i] = 8 * (fl_green[i] / 8);
- fl_blue[i] = 8 * (fl_blue[i] / 8);
- }
- }
-
- void fl_color(int col)
- /* Sets a colormap index in RGB mode. */
- {
- if (fl_rgbmode)
- RGBcolor(fl_red[col],fl_green[col],fl_blue[col]);
- else
- color(col);
- }
-
- void fl_mapcolor(int i, short red, short green, short blue)
- /* Changes a colormap index */
- {
- if (fl_rgbmode)
- { fl_red[i] = red; fl_green[i] = green; fl_blue[i] = blue;}
- else
- mapcolor(i,red,green,blue);
- }
-
- void fl_getmcolor(int i, short *red, short *green, short *blue)
- /* Returns a colormap index */
- {
- if (fl_rgbmode)
- {*red = fl_red[i]; *green = fl_green[i]; *blue = fl_blue[i];}
- else
- getmcolor(i,red,green,blue);
- }
-
- /*********
- Drawing boxes.
- *********/
-
- static void vv(float x,float y)
- { short v[2] ; v[0] = (short) x; v[1] = (short) y; v2s(v);}
-
- void fl_line(float x, float y, float w, float h, int col)
- /* Draws a line in the given color. */
- {
- fl_color(col);
- bgnline(); vv(x,y); vv(x+w-1.0,y+h-1.0); endline();
- }
-
- void fl_rect(float x, float y, float w, float h, int col)
- /* Draws a rectangle in the given color. */
- {
- fl_color(col);
- bgnpolygon();
- vv(x,y); vv(x+w,y); vv(x+w,y+h); vv(x,y+h);
- endpolygon();
- }
-
- void fl_bound(float x, float y, float w, float h, int col)
- /* Draws a boundary in the given color. */
- {
- fl_color(col);
- bgnclosedline();
- vv(x,y); vv(x+w-1.,y); vv(x+w-1.,y+h-1.); vv(x,y+h-1.);
- endclosedline();
- }
-
- void fl_rectbound(float x, float y, float w, float h, int col)
- /* Draws a rectangle in the given color with a black boundary. */
- {
- fl_color(col);
- bgnpolygon();
- vv(x+1.,y+1.); vv(x+w-1.,y+1.); vv(x+w-1.,y+h-1.); vv(x+1.,y+h-1.);
- endpolygon();
- fl_color(0);
- bgnclosedline();
- vv(x,y); vv(x+w-1.,y); vv(x+w-1.,y+h-1.); vv(x,y+h-1.);
- endclosedline();
- }
-
- #define RN 5
- #define RS 15.0
-
- static float offset[RN] = { 0.0, 0.07612, 0.29289, 0.61732, 1.0};
-
- static void rbox(int fill, float x,float y,float w,float h)
- /* Draws a rounded box */
- {
- int i;
- float rsx ,rsy, rs;
- rsx = 0.4*w; rsy = 0.4*h;
- if (rsx > rsy) rs = rsy; else rs = rsx;
- if (rs > RS) rs = RS;
- rsx = rs; rsy = rs;
-
- if (fill) bgnpolygon(); else bgnclosedline();
- for (i=0; i<RN; i++)
- vv(x + offset[RN-i-1]*rsx, y + offset[i] * rsy);
- for (i=0; i<RN; i++)
- vv(x + offset[i]*rsx, y + h-1.0 - offset[RN-i-1] * rsy);
- for (i=0; i<RN; i++)
- vv(x + w-1.0 - offset[RN-i-1]*rsx, y + h-1.0 - offset[i] * rsy);
- for (i=0; i<RN; i++)
- vv(x + w-1.0 - offset[i]*rsx, y + offset[RN-i-1] * rsy);
- if (fill) endpolygon(); else endclosedline();
- }
-
- void fl_drw_box(int style,float x,float y,float w,float h,int c,float bw)
- /* Draws a box. */
- {
- if (style == FL_NO_BOX) return;
- switch (style)
- {
- case FL_ROUNDED_BOX:
- fl_color(c); rbox(1,x,y,w,h);
- fl_color(0); rbox(0,x,y,w,h);
- break;
- case FL_RFLAT_BOX:
- fl_color(c); rbox(1,x,y,w,h);
- break;
- case FL_RSHADOW_BOX:
- /* draw the shadow */
- fl_color(FL_RIGHT_BOUND_COL);
- fl_set_clipping(x+bw,y-bw,w,bw+2.0);
- rbox(1,x+bw,y-bw,w,h);
- fl_set_clipping(x+w-1.0,y,bw+1.0,h-bw);
- rbox(1,x+bw,y-bw,w,h);
- fl_set_clipping(x+w+bw-RS,y,RS,RS);
- rbox(1,x+bw,y-bw,w,h);
- fl_unset_clipping();
- /* draw the box */
- fl_color(c); rbox(1,x,y,w,h);
- fl_color(0); rbox(0,x,y,w,h);
- break;
- case FL_FRAME_BOX:
- fl_rect(x+2.,y+2.,w-4.,h-4.,c);
- fl_bound(x+1.,y,w-1.,h-1.,FL_LEFT_BOUND_COL);
- fl_color(FL_RIGHT_BOUND_COL);
- bgnline(); vv(x,y); vv(x,y+h-1.); vv(x+w-1.,y+h-1.); endline();
- bgnline(); vv(x+2.,y+1.);vv(x+w-2.,y+1.);vv(x+w-2.,y+h-3.); endline();
- break;
- case FL_BORDER_BOX:
- fl_rectbound(x,y,w,h,c); break;
- case FL_FLAT_BOX:
- fl_rect(x,y,w,h,c); break;
- case FL_SHADOW_BOX:
- fl_rect(x+bw,y-bw,w,bw,FL_RIGHT_BOUND_COL);
- fl_rect(x+w,y-bw,bw,h,FL_RIGHT_BOUND_COL);
- fl_rectbound(x,y,w,h,c);
- break;
- case FL_UP_BOX:
- fl_rect(x+bw+1.,y+bw+1.,w-2*bw-2.,h-2*bw-2.,c);
- fl_rect(x+1.,y+h-bw-1.,w-2.,bw,FL_TOP_BOUND_COL);
- fl_rect(x+1.,y+1.,w-2.,bw,FL_BOT_BOUND_COL);
- fl_color(FL_RIGHT_BOUND_COL);
- bgnpolygon();
- vv(x+w-bw-1.,y+bw+1.); vv(x+w-bw-1.,y+h-bw-1.);
- vv(x+w-1.,y+h-1.); vv(x+w-1.,y+1.);
- endpolygon();
- fl_color(FL_LEFT_BOUND_COL);
- bgnpolygon();
- vv(x+1.,y+1.); vv(x+1.,y+h-1.);
- vv(x+bw+1.,y+h-bw-1.); vv(x+bw+1.,y+bw+1.);
- endpolygon();
- fl_bound(x,y,w,h,0);
- break;
- case FL_DOWN_BOX:
- fl_rectbound(x+bw,y+bw,w-2*bw,h-2*bw,c);
- fl_rect(x,y+h-bw,w,bw,FL_BOT_BOUND_COL);
- fl_rect(x,y,w,bw,FL_TOP_BOUND_COL);
- fl_color(FL_LEFT_BOUND_COL);
- bgnpolygon();
- vv(x+w-bw,y+bw); vv(x+w-bw,y+h-bw); vv(x+w,y+h); vv(x+w,y);
- endpolygon();
- fl_color(FL_RIGHT_BOUND_COL);
- bgnpolygon();
- vv(x,y); vv(x,y+h); vv(x+bw,y+h-bw); vv(x+bw,y+bw);
- endpolygon();
- break;
- default:
- fl_error("fl_draw_box","Unknown box type");
- break;
- }
- }
-
- /*********
- Drawing text.
- *********/
-
- #define NL 10
-
- /***
- Major text drawing routine
- ***/
-
- void fl_drw_string(
- int horalign, /* Horizontal alignment -1=left, 0=center, 1=right */
- int vertalign, /* Vertical alignment -1=bottom, 0=center, 1=top */
- float x, float y, float w, float h, /* Bounding box */
- int clip, /* Whether to clip to bounding box */
- int backcol, /* Background color */
- int forecol, /* Foreground color (text color) */
- int curscol, /* Cursor color */
- float size, /* Font size */
- int style, /* Font style */
- int curspos, /* The cursor position (-1 = no cursor) */
- int selstart,int selend, /* The selected region (end<start = no region) */
- char str[]) /* The (muli-line) string */
- {
- int i; /* counter */
- char tc; /* temporary character */
- float tt; /* temp value */
- char *lines[1024]; /* pointers to the start of the different lines */
- int start[1024]; /* start position of these lines */
- float startx[1024]; /* start x-coordinate of these lines */
- float starty[1024]; /* start y-coordinate of these lines */
- float width[1024]; /* string width of the lines */
- int lnumb; /* number of lines */
- fmfonthandle fnt; /* font to be used */
- fmfontinfo info; /* info of the font */
- float height; /* height of the font */
- float desc; /* descender of the font */
- int slstart,slend; /* Temporary selection positions */
- float xsel,wsel; /* position and width of selection area */
-
- /* Check whether anything has to be done */
- if (curspos != 0 && (str == NULL || str[0] == '\0')) return;
-
- /* Set the font to be used and get some info */
- fnt = use_font(style,size);
- if (fnt == NULL) return;
- fmsetfont(fnt);
- fmgetfontinfo(fnt,&info);
- height = info.ysize;
- desc = info.yorig;
-
- /* Set clipping if required */
- if (clip) fl_set_clipping(x,y,w,h);
-
- /* Split string into lines */
- lines[0] = &(str[0]);
- start[0] = 0;
- lnumb = 1;
- for (i = 0; str[i] != '\0'; i++)
- if (str[i] == NL)
- {
- str[i] = '\0';
- lines[lnumb] = &(str[i+1]);
- start[lnumb] = i+1;
- lnumb++;
- }
- start[lnumb] = i+1;
-
- /* Calculate start coordinates of lines */
- for (i = 0; i < lnumb; i++)
- {
- width[i] = fmgetstrwidth(fnt,lines[i]);
- if (horalign == -1) startx[i] = x;
- if (horalign == 0) startx[i] = x + 0.5*(w-width[i]);
- if (horalign == 1) startx[i] = x + w - width[i];
- if (vertalign == -1) starty[i] = y - (i - lnumb)*height;
- if (vertalign == 0) starty[i] = y + 0.5*h - (i - 0.5*lnumb)*height;
- if (vertalign == 1) starty[i] = y + h - i*height;
- }
-
- /* Draw the lines */
- for (i = 0; i < lnumb; i++)
- {
- /* Check whether visible */
- if (clip && starty[i]-height > y+h) continue;
- if (clip && starty[i] < y) break;
- /* Draw it */
- cmov2(startx[i],starty[i]-height+desc);
- fl_color(forecol);
- fmprstr(lines[i]);
- /* Draw selection area if required. */
- if (selstart < start[i+1] && selend >start[i])
- {
- if (selstart <= start[i]) slstart = start[i]; else slstart = selstart;
- if (selend >= start[i+1]) slend = start[i+1]-1; else slend = selend;
- tc = str[slstart];
- str[slstart] = '\0';
- xsel = startx[i] + fmgetstrwidth(fnt,lines[i]);
- str[slstart] = tc;
- tc = str[slend];
- str[slend] = '\0';
- wsel = fmgetstrwidth(fnt,&(str[slstart]));
- fl_rect(xsel,starty[i]-height,wsel,height,forecol);
- cmov2(xsel,starty[i]-height+desc);
- fl_color(backcol);
- fmprstr(&(str[slstart]));
- str[slend] = tc;
- }
- }
-
- /* Draw the cursor */
- if (curspos >= 0)
- {
- i=0; while (start[i] <= curspos) i++;
- i--;
- tc = str[curspos];
- str[curspos] = '\0';
- tt = fmgetstrwidth(fnt,lines[i]);
- str[curspos] = tc;
- fl_rect(startx[i]+tt,starty[i]-height,2.,height,curscol);
- }
-
- /* Restore the original string. */
- for (i = 1; i < lnumb; i++)
- str[start[i]-1] = NL;
-
- /* Reset clipping if required */
- if (clip) fl_unset_clipping();
- }
-
- /***
- Next routine returns the position of the mouse in a string
- ***/
-
- int fl_get_pos_in_string(
- int horalign, /* Horizontal alignment -1=left, 0=center, 1=right */
- int vertalign, /* Vertical alignment -1=bottom, 0=center, 1=top */
- float x, float y, float w, float h, /* Bounding box */
- float size, /* Font size */
- int style, /* Font style */
- float xpos, float ypos, /* Position of the mouse */
- char str[]) /* The (muli-line) string */
- {
- int i; /* counter */
- char tc; /* temporary character */
- int start[1024]; /* start position of the lines */
- int lnumb; /* number of lines */
- int theline; /* number of line in which the mouse lies */
- char *line; /* line in which mouse lies */
- float startx; /* start x-coordinate of this line */
- float width; /* string width of this line */
- fmfonthandle fnt; /* font to be used */
- fmfontinfo info; /* info of the font */
- float height; /* height of the font */
- float toppos; /* y-coord of the top line */
-
- /* Check whether anything has to be done */
- if (str == NULL || str[0] == '\0') return 0;
-
- /* Set the font to be used and get some info */
- fnt = use_font(style,size);
- if (fnt == NULL) return 0;
- fmsetfont(fnt);
- fmgetfontinfo(fnt,&info);
- height = info.ysize;
-
- /* Split string into lines */
- start[0] = 0;
- lnumb = 1;
- for (i = 0; str[i] != '\0'; i++)
- if (str[i] == NL) start[lnumb++] = i+1;
- start[lnumb] = i+1;
-
- /* Calculate line in which mouse lies */
- if (vertalign == -1) toppos = y - lnumb*height;
- if (vertalign == 0) toppos = y + 0.5*h + 0.5*lnumb*height;
- if (vertalign == 1) toppos = y + h;
- theline = (int) ((toppos - ypos)/height);
- if (theline < 0) return 0;
- if (theline >= lnumb) return strlen(str);
- line = &(str[start[theline]]);
-
- /* Calculate start coordinate of the line */
- tc = str[start[theline+1]-1];
- str[start[theline+1]-1] = '\0';
- width = fmgetstrwidth(fnt,line);
- if (horalign == -1) startx = x;
- if (horalign == 0) startx = x + 0.5*(w-width);
- if (horalign == 1) startx = x + w - width;
- str[start[theline+1]-1] = tc;
-
- for (i = start[theline]+1; i < start[theline+1]; i++)
- {
- tc = str[i];
- str[i] = '\0';
- if (xpos-startx <= fmgetstrwidth(fnt,line)) { str[i] = tc; return i-1;}
- str[i] = tc;
- }
- return start[theline+1]-1;
- }
-
- /***
- Misselaneous text drawing routines
- ***/
-
- void fl_drw_text_cursor(int align,float x,float y,float w,float h,
- int c,float size,int style,char str[],int cc,int pos)
- /* Draws a (multi-line) text with a cursor. */
- {
- int horalign,vertalign;
- float height = fl_get_char_height(size,style);
-
- switch (align) {
- case FL_ALIGN_LEFT: horalign = -1; vertalign = 0; break;
- case FL_ALIGN_RIGHT: horalign = 1; vertalign = 0; break;
- case FL_ALIGN_CENTER: horalign = 0; vertalign = 0; break;
- case FL_ALIGN_TOP: horalign = 0; vertalign = 1; break;
- case FL_ALIGN_BOTTOM: horalign = 0; vertalign = -1; break;
- }
- fl_drw_string(horalign,vertalign,
- x+0.5*height,y+0.25*height,w-height,h-0.5*height,
- FALSE,
- 7,c,cc,
- size,style,
- pos,
- 0,-1,
- str);
- }
-
- void fl_drw_text(int align,float x,float y,float w,float h,
- int c,float size,int style,char str[])
- /* Draws a text inside a box. */
- {
- if (str == NULL || str[0] == '\0') return;
- if (str[0] == '@') if (fl_draw_symbol(str,x,y,w,h,c)) return;
- fl_drw_text_cursor(align,x,y,w,h,c,size,style,str,0,-1);
- }
-
- void fl_drw_text_beside(int align,float x,float y,float w,float h,
- int c,float size,int style, char str[])
- /* Draws a text besides a box. */
- {
- if (str == NULL || str[0] == '\0') return;
- if (align == FL_ALIGN_LEFT)
- fl_drw_text(FL_ALIGN_RIGHT,x-h,y,h,h,c,size,style,str);
- else if (align == FL_ALIGN_RIGHT)
- fl_drw_text(FL_ALIGN_LEFT,x+w,y,h,h,c,size,style,str);
- else if (align == FL_ALIGN_TOP)
- fl_drw_text(FL_ALIGN_BOTTOM,x,y+h,w,h,c,size,style,str);
- else if (align == FL_ALIGN_BOTTOM)
- fl_drw_text(FL_ALIGN_TOP,x,y-h,w,h,c,size,style,str);
- else
- fl_drw_text(FL_ALIGN_CENTER,x,y,w,h,c,size,style,str);
- }
-